
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <semaphore.h>
#include <errno.h>


#define BUF_SIZE 10
void add_count(FILE *);

unsigned long count;
int size = sizeof(count);
sem_t *sema;
char* self;
void main(){
	FILE * file = fopen("counter.dat","wb");
	if(file == NULL){
		perror("cannot open file");
		return;
	}

	// place semaphore in shared mem
	sema = mmap(NULL,sizeof (sema),
		PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,
		-1,0);
	if(sema == MAP_FAILED){
		perror("mmap error");
		return;
	}

	// create/init semaphore
	if(sem_init(sema,1,0)<0){
		perror("sem_init error");
		return;
	}


	pid_t pid[1];

	pid[0] = fork();

	if(pid[0] == -1){
		printf("fork error\n");
		return;
	}
	if(pid[0] ==0){
		self = "child";
		printf("child process\n");
		while(1){
			add_count(file);
			printf("child, count=%ld\n", count);
		}
	}else{
		self="parent";
		printf("parent process\n");
		printf("parent release sema\n");
		if (sem_post(sema) < 0) {
			perror("sem_post");
		}
		while(1){
			add_count(file);
			printf("parent, count=%ld\n", count);
		}
	}

	wait(0);
}

// size_t fread (void *ptr, size_t size, size_t nmemb, FILE *stream);
// size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
void add_count(FILE * file){
	int i=0;
	// wait
	printf("%s wait sema\n", self);
	if(sem_wait(sema)<0){
		perror("sem_wait error");
		return;
	}
	printf("%s get sema\n", self);
	for(;i<10000; i++){
		int sz = fread(&count,size,1,file);
		// printf("read size=%d\n",sz);
		count++;
		fseek(file,0,SEEK_SET);
		fwrite(&count,size,1,file);
	}
	// unlock
	if(sem_post(sema)<0){
		perror("sem_post error");
		return;
	}
	printf("%s release sema\n", self);
}